package io.scnb.lesson002.demo7;

import org.junit.Test;
import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;

/**
 * InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation返回false，可以跳过bean属性的赋值
 */
public class InstantiationAwareBeanPostProcessoryTest1 {
    
    @Test
    public void test1() {
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        
        factory.registerBeanDefinition("user1", BeanDefinitionBuilder
                .genericBeanDefinition(UserModel.class)
                .addPropertyValue("name", "scnb")
                .addPropertyValue("age", 30)
                .getBeanDefinition()
        );
        
        factory.registerBeanDefinition("user2", BeanDefinitionBuilder
                .genericBeanDefinition(UserModel.class)
                .addPropertyValue("name", "刘德华")
                .addPropertyValue("age", 50)
                .getBeanDefinition()
        );
        
        for (String beanName : factory.getBeanDefinitionNames()) {
            System.out.println(String.format("%s->%s", beanName, factory.getBean(beanName)));
        }
    }

    @Test
    public void test2() {
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();

        factory.registerBeanDefinition("user1", BeanDefinitionBuilder
                .genericBeanDefinition(UserModel.class)
                .addPropertyValue("name", "scnb")
                .addPropertyValue("age", 30)
                .getBeanDefinition()
        );

        factory.registerBeanDefinition("user2", BeanDefinitionBuilder
                .genericBeanDefinition(UserModel.class)
                .addPropertyValue("name", "刘德华")
                .addPropertyValue("age", 50)
                .getBeanDefinition()
        );

        // 向容器中加入一个BeanPostProcessor，当遇到名称为user1的bean后，跳过属性赋值
        factory.addBeanPostProcessor(new InstantiationAwareBeanPostProcessor() {
            @Override
            public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
                if ("user1".equalsIgnoreCase(beanName)) {
                    return false;
                } else {
                    return true;
                }
            }
        });

        for (String beanName : factory.getBeanDefinitionNames()) {
            System.out.println(String.format("%s->%s", beanName, factory.getBean(beanName)));
        }
    }
    
    @Test
    public void test3() {
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        
        factory.addBeanPostProcessor(new InstantiationAwareBeanPostProcessor() {
            // 在postProcessProperties方法内部对user1这个bean进行属性值信息的修改
            @Override
            public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
                if ("user1".equalsIgnoreCase(beanName)) {
                    if (pvs == null) {
                        pvs = new MutablePropertyValues();
                    }
                    if (pvs instanceof MutablePropertyValues) {
                        MutablePropertyValues mpvs = (MutablePropertyValues) pvs;
                        mpvs.add("name", "路人");
                        mpvs.add("age", 18);
                    }
                }
                return null;
            }
        });

        factory.registerBeanDefinition("user1", BeanDefinitionBuilder
                .genericBeanDefinition(UserModel.class)
                .getBeanDefinition()
        );

        factory.registerBeanDefinition("user2", BeanDefinitionBuilder
                .genericBeanDefinition(UserModel.class)
                .addPropertyValue("name", "刘德华")
                .addPropertyValue("age", 50)
                .getBeanDefinition()
        );

        for (String beanName : factory.getBeanDefinitionNames()) {
            System.out.println(String.format("%s->%s", beanName, factory.getBean(beanName)));
        }
    }
    
}
